package com.dongdongshop.service.impl;

import com.alibaba.dubbo.config.annotation.Service;
import com.dongdongshop.constant.SeckillConstant;
import com.dongdongshop.mapper.TbSeckillGoodsMapper;
import com.dongdongshop.mapper.TbSeckillOrderMapper;
import com.dongdongshop.pojo.seckill.TbSeckillGoods;
import com.dongdongshop.pojo.seckill.TbSeckillGoodsExample;
import com.dongdongshop.pojo.seckill.TbSeckillOrder;
import com.dongdongshop.service.SeckillGoodsServiceI;
import com.dongdongshop.util.IdWorker;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
@Service
public class SeckillGoodsServiceImpl implements SeckillGoodsServiceI {

    @Resource
    private RedisTemplate redisTemplate;

    @Resource
    private TbSeckillGoodsMapper seckillGoodsMapper;

    @Resource
    private IdWorker idWorker;

    @Resource
    private RocketMQTemplate rocketMQTemplate;

    @Resource
    private TbSeckillOrderMapper seckillOrderMapper;

    /**
     * 更改缓存中订单的状态并同步到数据库
     * @param userId1
     */
    @Override
    public void updateOrderByUserId(String userId1) {
        TbSeckillOrder seckillOrder = (TbSeckillOrder)redisTemplate.boundHashOps(SeckillConstant.SECKILLORDERList).get(Long.parseLong(userId1));
        seckillOrder.setStatus("1");//已支付
        redisTemplate.boundHashOps(SeckillConstant.SECKILLORDERList).put(Long.parseLong(userId1),seckillOrder);
        //同步数据库
        seckillOrderMapper.updateByPrimaryKeySelective(seckillOrder);
    }

    /**
     * 从redis中查询订单
     * @param id
     * @return
     */
    @Override
    public TbSeckillOrder getOrderId(Long id) {
        return (TbSeckillOrder)redisTemplate.boundHashOps(SeckillConstant.SECKILLORDERList).get(id);
    }

    /**
     * 秒杀下单
     * @param id
     * @param userId
     */
    @Override
    public void submitOrder(Long id, Long userId) {
        //设置序列话
        redisTemplate.setValueSerializer(new StringRedisSerializer());
        //从缓存中查询出要秒杀的商品
        TbSeckillGoods seckillGoods =(TbSeckillGoods) redisTemplate.boundHashOps(SeckillConstant.SECKILLGOODSLIST).get(id);
        Integer stockCount=Integer.parseInt(redisTemplate.boundValueOps(id).get()+"");
        if (null == seckillGoods){
            //通过抛异常的方式通知controller信息 相当retur
            throw new RuntimeException("商品不存在");
        }
        //库存                   //如果int值小于128 可以不写.intValue()
        if (stockCount <=0){
            throw new RuntimeException("商品已售罄");
        }

        //扣减库存
        //seckillGoods.setStockCount(seckillGoods.getStockCount() - 1);
        Long decrement = redisTemplate.boundValueOps(id).decrement();
        seckillGoods.setStockCount(decrement.intValue());
        //将剪完的库存放到redis中
        redisTemplate.boundHashOps(SeckillConstant.SECKILLGOODSLIST).put(id,seckillGoods);
        //如果商品已售罄，同步数据库 删除redis
        //防止出现两个 0 的情况
        if (decrement.intValue() <= 0){
            System.out.println("11:"+seckillGoods.getStockCount());
            seckillGoodsMapper.updateByPrimaryKeySelective(seckillGoods);
            redisTemplate.boundHashOps(SeckillConstant.SECKILLGOODSLIST).delete(id);
        }
        //保存订单 mq异步生成订单
        Map<String,Long> map = new HashMap<>();
        map.put("seckillId",seckillGoods.getId());
        map.put("userId",userId);
        rocketMQTemplate.convertAndSend("createOrder",map);
    }

    //从redis中查询出来
    @Override
    public TbSeckillGoods getGoodsById(Long id) {
        TbSeckillGoods seckillGoods =(TbSeckillGoods) redisTemplate.boundHashOps(SeckillConstant.SECKILLGOODSLIST).get(id);
        return seckillGoods;
    }

    @Override
    public List<TbSeckillGoods> findSeckillGoodsList() {
        redisTemplate.setValueSerializer(new StringRedisSerializer());
        //先查redis    //获取hash类型的所有value值
        List<TbSeckillGoods> seckillGood = redisTemplate.boundHashOps(SeckillConstant.SECKILLGOODSLIST).values();
        //如果redis中没有
        if (null == seckillGood || seckillGood.size() <=0 ){
            //查询审核通过的 库存大于0的 已经开始的 还未结束的秒杀商品
            TbSeckillGoodsExample example = new TbSeckillGoodsExample();
            TbSeckillGoodsExample.Criteria criteria = example.createCriteria();
            criteria.andStatusEqualTo("1");//审核已通过
            criteria.andStartTimeLessThanOrEqualTo(new Date());//秒杀开始时间小于或者等于当前时间
            criteria.andEndTimeGreaterThanOrEqualTo(new Date());//秒杀结束时间大于或者等于当前时间
            criteria.andStockCountGreaterThan(0);//库存大于0
            List<TbSeckillGoods> seckillGoodsList=seckillGoodsMapper.selectByExample(example);
            //讲数据保存到redis中
            seckillGoodsList.stream().forEach(e->{
                redisTemplate.boundHashOps(SeckillConstant.SECKILLGOODSLIST).put(e.getId(),e);
                //秒杀预减库存
                redisTemplate.boundValueOps(e.getId()).set(e.getStockCount().toString());

            });
            return seckillGoodsList;
        }
        return seckillGood;
    }
}
